﻿using System;
using GeoAPI.Geometries;

namespace YJKGridTopologyCal.Operation.Buffer.Validate
{
	public class BufferCurveMaximumDistanceFinder
	{
		public BufferCurveMaximumDistanceFinder(IGeometry inputGeom)
		{
			this._inputGeom = inputGeom;
		}

		public double FindDistance(IGeometry bufferCurve)
		{
			this.ComputeMaxVertexDistance(bufferCurve);
			this.computeMaxMidpointDistance(bufferCurve);
			return this._maxPtDist.Distance;
		}

		public PointPairDistance DistancePoints
		{
			get
			{
				return this._maxPtDist;
			}
		}

		private void ComputeMaxVertexDistance(IGeometry curve)
		{
			BufferCurveMaximumDistanceFinder.MaxPointDistanceFilter maxPointDistanceFilter = new BufferCurveMaximumDistanceFinder.MaxPointDistanceFilter(this._inputGeom);
			curve.Apply(maxPointDistanceFilter);
			this._maxPtDist.SetMaximum(maxPointDistanceFilter.MaxPointDistance);
		}

		private void computeMaxMidpointDistance(IGeometry curve)
		{
			BufferCurveMaximumDistanceFinder.MaxMidpointDistanceFilter maxMidpointDistanceFilter = new BufferCurveMaximumDistanceFinder.MaxMidpointDistanceFilter(this._inputGeom);
			curve.Apply(maxMidpointDistanceFilter);
			this._maxPtDist.SetMaximum(maxMidpointDistanceFilter.MaxPointDistance);
		}

		private readonly IGeometry _inputGeom;

		private readonly PointPairDistance _maxPtDist = new PointPairDistance();

		public class MaxPointDistanceFilter : ICoordinateFilter
		{
			public MaxPointDistanceFilter(IGeometry geom)
			{
				this.geom = geom;
			}

			public void Filter(Coordinate pt)
			{
				this.minPtDist.Initialize();
				DistanceToPointFinder.ComputeDistance(this.geom, pt, this.minPtDist);
				this.maxPtDist.SetMaximum(this.minPtDist);
			}

			public PointPairDistance MaxPointDistance
			{
				get
				{
					return this.maxPtDist;
				}
			}

			private readonly PointPairDistance maxPtDist = new PointPairDistance();

			private readonly PointPairDistance minPtDist = new PointPairDistance();

			private readonly IGeometry geom;
		}

		public class MaxMidpointDistanceFilter : ICoordinateSequenceFilter
		{
			public MaxMidpointDistanceFilter(IGeometry geom)
			{
				this.geom = geom;
			}

			public void Filter(ICoordinateSequence seq, int index)
			{
				if (index == 0)
				{
					return;
				}
				Coordinate coordinate = seq.GetCoordinate(index - 1);
				Coordinate coordinate2 = seq.GetCoordinate(index);
				Coordinate pt = new Coordinate((coordinate.X + coordinate2.X) / 2.0, (coordinate.Y + coordinate2.Y) / 2.0);
				this.minPtDist.Initialize();
				DistanceToPointFinder.ComputeDistance(this.geom, pt, this.minPtDist);
				this.maxPtDist.SetMaximum(this.minPtDist);
			}

			public bool GeometryChanged
			{
				get
				{
					return false;
				}
			}

			public bool Done
			{
				get
				{
					return false;
				}
			}

			public PointPairDistance MaxPointDistance
			{
				get
				{
					return this.maxPtDist;
				}
			}

			private readonly PointPairDistance maxPtDist = new PointPairDistance();

			private readonly PointPairDistance minPtDist = new PointPairDistance();

			private readonly IGeometry geom;
		}
	}
}
